package boardgamer.yavalath.common.ai;

import boardgamer.common.CyclicIterator;
import boardgamer.common.net.PlayerId;
import boardgamer.yavalath.common.GeneratesMove;
import boardgamer.yavalath.common.YavalathBoard;
import boardgamer.yavalath.common.YavalathGameState;
import boardgamer.yavalath.common.YavalathTile;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;

import javax.annotation.Nullable;
import java.util.Random;

/**
 * Generates random moves (but follows the rules).
 *
 * Steven Fraim (stevenfraim@gmail.com)
 */
public class RandomAi implements GeneratesMove {

  @Override
  public YavalathTile getMove(YavalathGameState state) {
    YavalathTile tile = getForcedMove(state);
    return tile != null ? tile : getRandomMove(state);
  }

  private YavalathTile getRandomMove(YavalathGameState state) {
    int gridSize = state.getBoard().getSide();
    Random rand = new Random(System.nanoTime());

    int x, y;
    do {
      x = rand.nextInt(gridSize);
      y = rand.nextInt(gridSize);
    } while(state.getBoard().getTile(x, y).hasOwner() && !state.isSwappingAllowed());
    return state.getBoard().getTile(x, y);
  }

  private @Nullable YavalathTile getForcedMove(YavalathGameState state) {
    if (state.getActivePlayers().size() < 3) {
      return null;
    }
    PlayerId nextPlayer = CyclicIterator.copyOf(state.getActivePlayers()).next();

    Iterable<YavalathTile> nextWinningMoves = state.getNextWinningMoves(nextPlayer);

    // Remove tiles that have been owned
    final YavalathBoard boardCopy = YavalathBoard.copyOf(state.getBoard());
    Iterable<YavalathTile> unownedWinningMoves = Iterables.filter(
        nextWinningMoves,
        new Predicate<YavalathTile>() {
          @Override
          public boolean apply(YavalathTile input) {
            return !boardCopy.getTile(input.getX(), input.getY()).hasOwner();
          }
        });

    return Iterables.getFirst(unownedWinningMoves, null);
  }
}
